<?php
/**
 * Created by PhpStorm.
 * User: jaylen
 * Date: 2020-06-09
 * Time: 18:20
 */

namespace app\common\service;


use think\facade\Cache;
use think\facade\Config;

class WxAccessToken
{
    private $tokenUrl;  //请求access_token的url地址
    private $tokenCacheKey = '';  //access_token存放在缓存的key值
    const TOKEN_EXPIRE_IN = 7000;   //access_token存放在缓存的时间，微信为7200，所以这里使用7000保证access_token有效

    public function __construct($token_cache_key)
    {
        $url = Config::get('wx.access_token_url');
        $url = sprintf($url,
            get_wx_config('mp_app_id'),
            get_wx_config('mp_app_secret'));

        $this->tokenUrl = $url;
        $this->tokenCacheKey = $token_cache_key;
    }

    /**
     * 获取access_token
     * 建议用户规模小时，每次直接去微信服务器取最新的token
     * 但微信access_token接口获取是有限制的 2000次/天
     * @return mixed
     * @throws \throwable
     */
    public function get()
    {
        return Cache::remember($this->tokenCacheKey,function () {
            return $this->getAccessTokenFromWx();
        },self::TOKEN_EXPIRE_IN);
    }

    /**
     * 从微信服务器中获取access_token
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function getAccessTokenFromWx()
    {
        // 从微信服务器获取access_token
        $accessToken = curl_get($this->tokenUrl);
        $accessToken = json_decode($accessToken,true);

        if (empty($accessToken)) {
            throw new \Exception('获取微信Access_token异常');
        }

        if (isset($accessToken['errcode']) && $accessToken['errcode'] != 0) {
            throw new \Exception('获取Access_toekn失败，错误代码为：' . $accessToken['errcode'] . ' 信息：' . $accessToken['errmsg']);
        }

        // 将获取到的access_token 保存到缓存中
        $this->saveToCache($accessToken['access_token']);

        return $accessToken['access_token'];
    }

    /**
     * 将access_token保存到缓存中
     * @param $accessToken
     */
    protected function saveToCache($accessToken)
    {
        Cache::set($this->tokenCacheKey, $accessToken, self::TOKEN_EXPIRE_IN);
    }
}